package com.yy.invoice.service.impl;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.extra.mail.MailUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yy.invoice.entity.LoginUser;
import com.yy.invoice.entity.Result;
import com.yy.invoice.entity.User;
import com.yy.invoice.mapper.UserMapper;
import com.yy.invoice.service.UserService;
import com.yy.invoice.utils.JwtUtil;
import com.yy.invoice.utils.RedisCache;
import com.yy.invoice.vo.UserVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Objects;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author yang1yu
 * @since 2022-09-27
 */
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private AuthenticationManager authenticationManager;

    @Override
    public Result login(User user) {
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(user.getUsername(),user.getPassword());
        Authentication authenticate = authenticationManager.authenticate(authenticationToken);
        if(Objects.isNull(authenticate)){
            throw new RuntimeException("用户名或密码错误");
        }
        //使用userid生成token
        LoginUser loginUser = (LoginUser) authenticate.getPrincipal();
        String userId = loginUser.getUser().getUserId().toString();
        String jwt = JwtUtil.createJWT(userId);
        //authenticate存入redis
        redisCache.setCacheObject("login:"+userId,loginUser);
        //把token响应给前端
        HashMap<String,String> map = new HashMap<>();
        map.put("token",jwt);
        return new Result("success",0,map);
    }

    @Override
    public Result register(User user) {
        BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
        log.info("user:" + user);
        String encode = bCryptPasswordEncoder.encode(user.getPassword());
        user.setPassword(encode);
        int insert = userMapper.insert(user);
        if(insert == 1){
            return new Result("success",0);
        }else {
            return new Result("error",1);
        }
    }

    @Override
    public Result loginOut() {
        //获取SecurityContextHolder中的用户id
        UsernamePasswordAuthenticationToken authentication = (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
        Integer userId = loginUser.getUser().getUserId();
        boolean b = redisCache.deleteObject("login:" + userId);
        if(b){
            return new Result("注销成功",0);
        }else{
            return new Result("注销失败",1);
        }
    }

    @Override
    public Result get(HttpServletRequest request) {
        Result result = new Result();
        try {
            String userId = JwtUtil.parseJWT(request.getHeader("token")).getSubject();
            LoginUser loginUser = redisCache.getCacheObject("login:" + userId);
            result.setMessage("success");
            result.setCode(0);
            UserVo userVo = new UserVo();
            userVo.setEmail(loginUser.getUser().getEmail());
            userVo.setTel(loginUser.getUser().getTel());
            userVo.setUsername(loginUser.getUsername());
            result.setData(userVo);
        } catch (Exception e) {
            result.setMessage("error");
            result.setCode(1);
            throw new RuntimeException(e);
        }
        return result;
    }

    @Override
    public Result checkUsername(String username) {
        Result result = new Result();
        User user = userMapper.selectOne(
                new LambdaQueryWrapper<User>()
                        .eq(User::getUsername, username)
        );
        if(user ==null){
            result.setCode(0);
            result.setMessage("用户不存在可以进行注册");
        }else {
            result.setCode(1);
            result.setMessage("用户存在不能注册");
        }
        return result;
    }

    @Override
    public Result updateUser(User user,HttpServletRequest request) {
        Result result = new Result();
        try {
            String userId = JwtUtil.parseJWT(request.getHeader("token")).getSubject();
            user.setUserId(Integer.valueOf(userId));
            String rawPassword = user.getPassword();
            int update = 0;
            if(!StringUtils.hasText(rawPassword) || rawPassword == null){
                update = userMapper.updateById(user);
            }else {
                String encode = new BCryptPasswordEncoder().encode(rawPassword);
                user.setPassword(encode);
                update = userMapper.updateById(user);
            }
            if(update == 1){
                redisCache.deleteObject("login:" + userId);
                result.setMessage("update success,please login again!");
                result.setCode(0);
            }else {
                result.setMessage("update error,please try again!");
                result.setCode(1);
            }
        } catch (Exception e) {
            result.setMessage("update error");
            result.setCode(1);
        }
        return result;
    }

    @Override
    public Result reset(User user) {
        Result result = new Result();
        User resetUser = userMapper.selectOne(
                new LambdaQueryWrapper<User>()
                        .eq(User::getUsername, user.getUsername())
                        .eq(User::getEmail, user.getEmail())
        );
        if(Objects.isNull(resetUser) || resetUser == null){
            result.setMessage("用户名或邮箱错误");
            result.setCode(1);
        }else {
            String rawPassword = RandomUtil.randomString(8);
            resetUser.setPassword(new BCryptPasswordEncoder().encode(rawPassword));
            MailUtil.send(resetUser.getEmail(),"重置密码","你重置的密码为：" + rawPassword + " 请重新登录后修改密码" ,false);
            int i = userMapper.updateById(resetUser);
            if(i == 1){
                result.setCode(0);
                result.setMessage("reset success");
            }else {
                result.setCode(1);
                result.setMessage("reset error");
            }
        }
        return result;
    }
}
